package com.penghaonan.appframework.utils

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.PixelFormat
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import android.provider.MediaStore
import androidx.core.graphics.createBitmap
import com.penghaonan.appframework.AppDelegate.getApp
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.IOException


object BitmapUtils {
    fun rotate(bm: Bitmap, orientationDegree: Int, config: Bitmap.Config): Bitmap {
        val m = Matrix()
        m.setRotate(
            orientationDegree.toFloat(),
            bm.getWidth().toFloat() / 2,
            bm.getHeight().toFloat() / 2
        )
        val targetX: Float
        val targetY: Float
        if (orientationDegree == 90) {
            targetX = bm.getHeight().toFloat()
            targetY = 0f
        } else {
            targetX = bm.getHeight().toFloat()
            targetY = bm.getWidth().toFloat()
        }

        val values = FloatArray(9)
        m.getValues(values)

        val x1 = values[Matrix.MTRANS_X]
        val y1 = values[Matrix.MTRANS_Y]

        m.postTranslate(targetX - x1, targetY - y1)

        val bm1 = createBitmap(bm.getHeight(), bm.getWidth(), config)
        val paint = Paint()
        val canvas = Canvas(bm1)
        canvas.drawBitmap(bm, m, paint)

        return bm1
    }

    /**
     * drawable 转 bitmap
     *
     * @param drawable
     * @return
     */
    @JvmOverloads
    fun drawable2Bitmap(drawable: Drawable?, size: Pair<Int, Int>? = null): Bitmap? {
        if (drawable == null) {
            return null
        }
        if (drawable is BitmapDrawable) {
            val bd = drawable
            return bd.bitmap
        } else {
            if (drawable.intrinsicWidth > 0 && drawable.intrinsicHeight > 0) {
                val bitmap = createBitmap(
                    size?.first ?: drawable.intrinsicWidth,
                    size?.second ?: drawable.intrinsicHeight,
                    if (drawable.opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
                )
                val canvas = Canvas(bitmap)
                drawable.setBounds(
                    0, 0, drawable.intrinsicWidth,
                    drawable.intrinsicHeight
                )
                drawable.draw(canvas)
                return bitmap
            } else {
                return null
            }
        }
    }


    fun getRatioBitmap(imgId: Int, reqWidth: Int, reqHeight: Int): Bitmap? {
        val newOpts = BitmapFactory.Options()
        newOpts.inJustDecodeBounds = true
        BitmapFactory.decodeResource(getApp().resources, imgId, newOpts)
        newOpts.inSampleSize = calculateInSampleSize(newOpts, reqWidth, reqHeight)

        newOpts.inJustDecodeBounds = false
        return BitmapFactory.decodeResource(getApp().resources, imgId, newOpts)
    }


    private fun calculateInSampleSize(
        options: BitmapFactory.Options,
        reqWidth: Int,
        reqHeight: Int
    ): Int {
        val height = options.outHeight
        val width = options.outWidth
        var inSampleSize = 1
        if (height > reqHeight || width > reqWidth) {
            val halfHeight = height / 2
            val halfWidth = width / 2
            while ((halfHeight / inSampleSize >= reqHeight) && (halfWidth / inSampleSize >= reqWidth)) {
                inSampleSize *= 2
            }
        }
        return inSampleSize
    }

    /**
     * 转化成灰度图
     */
    fun toGrayscale(bmpOriginal: Bitmap): Bitmap {
        val height: Int = bmpOriginal.getHeight()
        val width: Int = bmpOriginal.getWidth()

        val bmpGrayscale = createBitmap(width, height, Bitmap.Config.RGB_565)
        val c = Canvas(bmpGrayscale)
        val paint = Paint()
        val cm = ColorMatrix()
        cm.setSaturation(0f)
        val f = ColorMatrixColorFilter(cm)
        paint.setColorFilter(f)
        c.drawBitmap(bmpOriginal, 0f, 0f, paint)
        return bmpGrayscale
    }

    /**
     * Bitmap压缩
     */
    fun resizeBitmap(bm: Bitmap, reqWidth: Int, reqHeight: Int): Bitmap? {
        val width = bm.getWidth()
        val height = bm.getHeight()

        if (height > reqHeight || width > reqWidth) {
            val scaleWidth = reqWidth.toFloat() / width
            val scaleHeight = reqHeight.toFloat() / height
            val scale = if (scaleWidth < scaleHeight) scaleWidth else scaleHeight

            val matrix = Matrix()
            matrix.postScale(scale, scale)
            val result = Bitmap.createBitmap(
                bm, 0, 0, bm.getWidth(),
                bm.getHeight(), matrix, true
            )
            bm.recycle()
            return result
        }
        return bm
    }

    fun loadBitmap(uri: Uri?): Bitmap? {
        try {
            val bitmap = MediaStore.Images.Media.getBitmap(getApp().contentResolver, uri)
            return bitmap
        } catch (e: IOException) {
            Logger.e(e)
        }
        return null
    }

    fun compressImage(
        image: Bitmap?,
        format: Bitmap.CompressFormat,
        maxFileSize: Int = 200 * 1024
    ): Bitmap? {
        if (image == null) {
            return null
        }
        val baos = ByteArrayOutputStream()
        image.compress(format, 100, baos)
        var options = 90
        while (baos.toByteArray().size > maxFileSize) {
            baos.reset()
            image.compress(
                format,
                options,
                baos
            )
            options -= 10
        }
        val isBm = ByteArrayInputStream(baos.toByteArray())
        val bitmap = BitmapFactory.decodeStream(isBm, null, null)
        return bitmap
    }
}
